package com.fmy.security.config;

import com.fmy.security.cache.CacheOnline;
import com.fmy.security.config.filter.LoginTypeFilter;
import com.fmy.security.config.filter.TokenContextHolderFilter;
import com.fmy.security.service.TokenExceptionHander;
import lombok.Getter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.session.ConcurrentSessionFilter;

/**
 * @author Mr.fmy
 * @version 1.0.0
 * @ClassName SecurityConfig.java
 * @Description TODO 配置类
 * @createTime 2019年07月06日 13:45:00
 */
public abstract class SecurityConfigAdapter extends WebSecurityConfigurerAdapter {

    private TokenContextHolderFilter tokenContextHolderFilter;
    private LoginTypeFilter loginTypeFilter;
    private CacheOnline cacheOnline;


    @Override
    public void init(WebSecurity web) throws Exception {
        super.init(web);
        customConfigure(this.getHttp());
    }

    private void customConfigure(HttpSecurity http) throws Exception {
        cacheOnline = getApplicationContext().getBean(CacheOnline.class);
        tokenContextHolderFilter = concurrentTokenFilter(http);
        loginTypeFilter = loginTypeFilter(http);
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.headers().cacheControl();
        loginConfig(http);
        configure(new Config(tokenContextHolderFilter, loginTypeFilter, cacheOnline));
    }

    protected void configure(Config config) {
    }

    private void loginConfig(HttpSecurity http) throws Exception {
        http.formLogin()
                .successHandler(getApplicationContext().getBean(AuthenticationSuccessHandler.class))
                .failureHandler(getApplicationContext().getBean(AuthenticationFailureHandler.class));
    }

    private TokenContextHolderFilter concurrentTokenFilter(HttpSecurity http) {
        TokenContextHolderFilter filter = new TokenContextHolderFilter(cacheOnline, getApplicationContext().getBean(TokenExceptionHander.class));
        http.addFilterAfter(filter, UsernamePasswordAuthenticationFilter.class);
        return filter;
    }

    private LoginTypeFilter loginTypeFilter(HttpSecurity http) {
        LoginTypeFilter filter = new LoginTypeFilter(getApplicationContext());
        http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
        return filter;
    }

    public LoginTypeFilter getLoginTypeFilter() {
        return loginTypeFilter;
    }


    public static class Config {
        @Getter
        private TokenContextHolderFilter tokenContextHolderFilter;
        @Getter
        private LoginTypeFilter loginTypeFilter;

        private CacheOnline cacheOnline;

        public Config(TokenContextHolderFilter tokenContextHolderFilter, LoginTypeFilter loginTypeFilter, CacheOnline cacheOnline) {
            this.tokenContextHolderFilter = tokenContextHolderFilter;
            this.loginTypeFilter = loginTypeFilter;
            this.cacheOnline = cacheOnline;
        }

        public Config setMaxRegister(int maxRegister) {
            cacheOnline.setMaxRegister(maxRegister);
            return this;
        }
    }
}
